package com.ckzp.core.file;

import cn.hutool.core.util.StrUtil;
import com.ckzp.core.util.StringUtil;
import com.jfinal.kit.FileKit;
import sun.net.www.protocol.http.HttpURLConnection;

import java.io.*;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

/**
 * Created by 51594 on 2022/7/28.
 */
public class FileUtil {
    /**
     * 文件操作类
     */
    private FileUtil() {

    }

    /**
     * 修改文件最后修改时间
     * 如果文件不存在，创建文件
     *
     * @param file
     */
    public static void touch(File file) {
        long currentTime = System.currentTimeMillis();
        if (!file.exists()) {
            try {
                if (file.createNewFile()) {
                } else {
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        boolean result = file.setLastModified(currentTime);
        if (!result) {
        }
    }

    /**
     * 修改文件最后修改时间
     * 如果文件不存在，创建文件
     *
     * @param fileName
     */
    public static void touch(String fileName) {
        File file = new File(fileName);
        touch(file);
    }

    /**
     * 创建空文件
     *
     * @param myFile
     * @return
     * @throws Exception
     */
    public boolean createFile(File myFile) throws Exception {
        if (myFile == null) {
            throw new FileNotFoundException();
        } else if (myFile.isDirectory()) {
            createDirectory(myFile);
            return true;
        } else {
            try {
                createDirectory(myFile);
                myFile.createNewFile();
                return true;
            } catch (IOException e) {
                throw e;
            }
        }
    }

    /**
     * 分层创建文件夹
     *
     * @param myFile
     * @return
     */
    public boolean createDirectory(File myFile) {
        boolean re = false;
        File tempFile = null;
        String tempFilePath = "";
        if (myFile.isFile()) {
            tempFile = myFile;
        } else {
            tempFile = myFile.getParentFile();
        }
        String path = StringUtil.getString(tempFile.getAbsolutePath(), "");
        path = StringUtil.replace(path, "\\", "/");
        path = StringUtil.replace(path, "\\", "/");
        String[] fileName = StringUtil.split(path, "/");
        for (int kk = 0; kk < fileName.length; kk++) {
            tempFilePath += fileName[kk] + "/";
            if (!tempFilePath.startsWith("/") && tempFilePath.indexOf(":") != 1) {
                tempFilePath = "/" + tempFilePath;
            }
            tempFile = new File(tempFilePath);
            re = tempFile.mkdir();
        }
        return re;
    }

    /**
     * 批量创建文件
     *
     * @param files
     */
    public static void touch(File[] files) {
        for (int i = 0; i < files.length; i++) {
            touch(files[i]);
        }
    }

    /**
     * 批量创建文件
     *
     * @param fileNames
     */
    public static void touch(String[] fileNames) {
        File[] files = new File[fileNames.length];
        for (int i = 0; i < fileNames.length; i++) {
            files[i] = new File(fileNames[i]);
        }
        touch(files);
    }

    /**
     * 判断 文件是否存在，是否是文件
     *
     * @param fileName
     * @return
     */
    public static boolean isFileExist(String fileName) {
        return new File(fileName).isFile();
    }

    /**
     * 创建父文件夹，只能创建一层
     *
     * @param file
     * @return
     */
    public static boolean makeDirectory(File file) {
        File parent = file.getParentFile();
        if (parent != null) {
            return parent.mkdirs();
        }
        return false;
    }

    /**
     * 创建父文件夹，只能创建一层
     *
     * @param fileName
     * @return
     */
    public static boolean makeDirectory(String fileName) {
        File file = new File(fileName);
        return makeDirectory(file);
    }


    /**
     * 清空文件夹
     *
     * @param directory
     * @return
     */
    public static boolean emptyDirectory(File directory) {
        boolean result = false;
        File[] entries = directory.listFiles();
        for (int i = 0; i < entries.length; i++) {
            if (!entries[i].delete()) {
                result = false;
            }
        }
        return true;
    }

    /**
     * 清空文件夹
     *
     * @param directoryName
     * @return
     */
    public static boolean emptyDirectory(String directoryName) {
        File dir = new File(directoryName);
        return emptyDirectory(dir);
    }

    /**
     * 删除文件夹
     *
     * @param dirName
     * @return
     */
    public static boolean deleteDirectory(String dirName) {
        return deleteDirectory(new File(dirName));
    }

    /**
     * 删除文件夹
     *
     * @param dir
     * @return
     */
    public static boolean deleteDirectory(File dir) {
        if ((dir == null) || !dir.isDirectory()) {
            throw new IllegalArgumentException("Argument " + dir + " is not a directory. ");
        }
        File[] entries = dir.listFiles();
        int sz = entries.length;
        for (int i = 0; i < sz; i++) {
            if (entries[i].isDirectory()) {
                if (!deleteDirectory(entries[i])) {
                    return false;
                }
            } else {
                if (!entries[i].delete()) {
                    return false;
                }
            }
        }
        if (!dir.delete()) {
            return false;
        }
        return true;
    }

    /**
     * 列出所有文件
     *
     * @param fileName
     * @return
     */
    public static File[] listAll(String fileName) {
        return listAll(new File(fileName));
    }

    /**
     * 列出所有文件
     *
     * @param file
     * @return
     */
    public static File[] listAll(File file) {
        ArrayList list = new ArrayList();
        File[] files;
        if (!file.exists() || file.isFile()) {
            return null;
        }
        list(list, file, null);
        list.remove(file);
        files = new File[list.size()];
        list.toArray(files);
        return files;
    }

    /**
     * 列出所有文件
     *
     * @param file
     * @param filter
     * @return
     */
    public static File[] listAll(File file, javax.swing.filechooser.FileFilter filter) {
        ArrayList list = new ArrayList();
        File[] files;
        if (!file.exists() || file.isFile()) {
            return null;
        }
        list(list, file, filter);
        files = new File[list.size()];
        list.toArray(files);
        return files;
    }

    /**
     * 列出所有文件
     *
     * @param list
     * @param file
     * @param filter
     */
    private static void list(ArrayList list, File file, javax.swing.filechooser.FileFilter filter) {
        if (filter != null) {
            if (filter.accept(file)) {
                list.add(file);
                if (file.isFile()) {
                    return;
                }
            }
        } else {
            list.add(file);
            if (file.isFile()) {
                return;
            }
        }
        if (file.isDirectory()) {
            File files[] = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                list(list, files[i], filter);
            }
        }

    }

    /**
     * 取文件显示路经
     *
     * @param file
     * @return
     * @throws MalformedURLException
     */
    public static URL getURL(File file) throws MalformedURLException {
        String fileURL = "file:/" + file.getAbsolutePath();
        URL url = new URL(fileURL);
        return url;
    }

    /**
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath) {
        File file = new File(filePath);
        return file.getName();
    }

    /**
     * @param fileName
     * @return
     */
    public static String getFilePath(String fileName) {
        File file = new File(fileName);
        return file.getAbsolutePath();
    }

    /**
     * @param filePath
     * @return
     */
    public static String toUNIXpath(String filePath) {
        return filePath.replace('\\', '/');
    }

    /**
     * @param fileName
     * @return
     */
    public static String getUNIXfilePath(String fileName) {
        File file = new File(fileName);
        return toUNIXpath(file.getAbsolutePath());
    }

    /**
     * @param fileName
     * @return
     */
    public static String getTypePart(String fileName) {
        int point = fileName.lastIndexOf('.');
        int length = fileName.length();
        if (point == -1 || point == length - 1) {
            return "";
        } else {
            return fileName.substring(point + 1, length);
        }
    }

    /**
     * @param file
     * @return
     */
    public static String getFileType(File file) {
        return getTypePart(file.getName());
    }

    /**
     * @param fileName
     * @return
     */
    public static String getNamePart(String fileName) {
        int point = getPathLsatIndex(fileName);
        int length = fileName.length();
        if (point == -1) {
            return fileName;
        } else if (point == length - 1) {
            int secondPoint = getPathLsatIndex(fileName, point - 1);
            if (secondPoint == -1) {
                if (length == 1) {
                    return fileName;
                } else {
                    return fileName.substring(0, point);
                }
            } else {
                return fileName.substring(secondPoint + 1, point);
            }
        } else {
            return fileName.substring(point + 1);
        }
    }

    /**
     * @param fileName
     * @return
     */
    public static String getPathPart(String fileName) {
        int point = getPathLsatIndex(fileName);
        int length = fileName.length();
        if (point == -1) {
            return "";
        } else if (point == length - 1) {
            int secondPoint = getPathLsatIndex(fileName, point - 1);
            if (secondPoint == -1) {
                return "";
            } else {
                return fileName.substring(0, secondPoint);
            }
        } else {
            return fileName.substring(0, point);
        }
    }

    /**
     * @param fileName
     * @return
     */
    public static int getPathIndex(String fileName) {
        int point = fileName.indexOf('/');
        if (point == -1) {
            point = fileName.indexOf('\\');
        }
        return point;
    }

    /**
     * @param fileName
     * @param fromIndex
     * @return
     */
    public static int getPathIndex(String fileName, int fromIndex) {
        int point = fileName.indexOf('/', fromIndex);
        if (point == -1) {
            point = fileName.indexOf('\\', fromIndex);
        }
        return point;
    }

    /**
     * @param fileName
     * @return
     */
    public static int getPathLsatIndex(String fileName) {
        int point = fileName.lastIndexOf('/');
        if (point == -1) {
            point = fileName.lastIndexOf('\\');
        }
        return point;
    }

    /**
     * @param fileName
     * @param fromIndex
     * @return
     */
    public static int getPathLsatIndex(String fileName, int fromIndex) {
        int point = fileName.lastIndexOf('/', fromIndex);
        if (point == -1) {
            point = fileName.lastIndexOf('\\', fromIndex);
        }
        return point;
    }

    /**
     * @param filename
     * @return
     */
    public static String trimType(String filename) {
        int index = filename.lastIndexOf(".");
        if (index != -1) {
            return filename.substring(0, index);
        } else {
            return filename;
        }
    }

    /**
     * @param pathName
     * @param fileName
     * @return
     */
    public static String getSubpath(String pathName, String fileName) {
        int index = fileName.indexOf(pathName);
        if (index != -1) {
            return fileName.substring(index + pathName.length() + 1);
        } else {
            return fileName;
        }
    }

    /**
     * @param oldFilePath
     * @param newFilePath
     * @throws IOException
     */
    public static void copyFile(String oldFilePath, String newFilePath) throws IOException {
        FileInputStream fi = new FileInputStream(oldFilePath);
        FileOutputStream fo = new FileOutputStream(newFilePath);
        byte data[] = new byte[fi.available()];
        fi.read(data);
        fo.write(data);
        fi.close();
        fo.close();
    }


    /**
     * @param filename
     * @return
     */
    public static String getFileExtName(String filename) {
        return filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toUpperCase();
    }

    /**
     * @param folderPath
     */
    public static boolean newFolder(String folderPath) {
        try {
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            if (!myFilePath.exists()) {
                return myFilePath.mkdir();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param filePathAndName
     * @param fileContent
     */
    public static void newFile(String filePathAndName, String fileContent) {

        try {
            String filePath = filePathAndName;
            filePath = filePath.toString();
            File myFilePath = new File(filePath);
            if (!myFilePath.exists()) {
                myFilePath.createNewFile();
            }
            FileWriter resultFile = new FileWriter(myFilePath);
            PrintWriter myFile = new PrintWriter(resultFile);
            String strContent = fileContent;
            myFile.println(strContent);
            myFile.close();
            resultFile.close();
        } catch (Exception e) {
            e.printStackTrace();

        }

    }

    /**
     * @param filePathAndName
     */
    public static void delFile(String filePathAndName) {
        try {
            String filePath = filePathAndName;
            filePath = filePath.toString();
            java.io.File myDelFile = new java.io.File(filePath);
            if (myDelFile.exists() && myDelFile.isFile()) {
                myDelFile.delete();
            }

        } catch (Exception e) {
            e.printStackTrace();

        }

    }

    /**
     * @param folderPath
     */
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath);
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            myFilePath.delete();

        } catch (Exception e) {
            e.printStackTrace();

        }

    }

    /**
     * @param path
     */
    public static void delAllFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return;
        }
        if (!file.isDirectory()) {
            return;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//
                delFolder(path + "/" + tempList[i]);//
            }
        }
    }


    /**
     * @param oldPath
     * @param newPath
     */
    public static void copyFolder(String oldPath, String newPath) {
        FileInputStream input = null;
        FileOutputStream output = null;
        try {
            boolean d = (new File(newPath)).mkdirs();
            File a = new File(oldPath);
            String[] file = a.list();
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file[i]);
                } else {
                    temp = new File(oldPath + File.separator + file[i]);
                }

                if (temp.isFile()) {
                    input = new FileInputStream(temp);
                    output = new FileOutputStream(newPath + "/" +
                            (temp.getName()).toString());
                    byte[] b = new byte[1024 * 5];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                if (temp.isDirectory()) {//
                    copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            safeCloseFileInputStream(input);
            safeCloseFileOutputStream(output);
        }
    }

    /**
     * @param oldPath
     * @param newPath
     * @throws Exception
     */
    public static void moveFile(String oldPath, String newPath) throws Exception {
        copyFile(oldPath, newPath);
        delFile(oldPath);

    }

    /**
     * @param oldPath
     * @param newPath
     */
    public static void moveFolder(String oldPath, String newPath) {
        copyFolder(oldPath, newPath);
        delFolder(oldPath);

    }

    public static boolean renameFolder(String srcPath, String dsPath) {//
        File srcFile = new File(srcPath);
        return srcFile.renameTo(new File(dsPath));
    }

    /**
     * @param size
     * @return
     */
    public static String getPrintSize(long size) {
        // 如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        double value = (double) size;
        if (value < 1024) {
            return String.valueOf(value) + "B";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        // 如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        // 因为还没有到达要使用另一个单位的时候
        // 接下去以此类推
        if (value < 1024) {
            return String.valueOf(value) + "KB";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        if (value < 1024) {
            return String.valueOf(value) + "MB";
        } else {
            // 否则如果要以GB为单位的，先除于1024再作同样的处理
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            return String.valueOf(value) + "GB";
        }
    }

    /**
     * @param remoteurl
     * @param localfile
     * @return
     */
    public static boolean downFileFromRemote(String remoteurl, String localfile) {
        URL urlfile = null;
        HttpURLConnection httpUrl = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        File f = new File(localfile);
        try {
            urlfile = new URL(remoteurl);
            httpUrl = (HttpURLConnection) urlfile.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            bos = new BufferedOutputStream(new FileOutputStream(f));
            int len = 2048;
            byte[] b = new byte[len];
            while ((len = bis.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            bos.flush();
            bis.close();
            httpUrl.disconnect();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                bis.close();
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    private static void safeCloseOutputStream(final BufferedInputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private static void safeCloseFileOutputStream(final FileOutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private static void safeCloseOutputStream(final FileOutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }


    private static void safeCloseFileInputStream(final FileInputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }


}